package com.my.chapter21;

import net.mindview.util.CountingGenerator;
import net.mindview.util.Generator;

import java.util.List;
import java.util.concurrent.*;

public class practice34 {
    static int size = 10;
    static int delay = 5;

    public static void main(String[] args) throws InterruptedException {
        if(args.length > 0)
            size = new Integer(args[0]);
        if(args.length > 1)
            delay = new Integer(args[1]);
        ExecutorService exec = Executors.newCachedThreadPool();
        Exchanger<List<Integer>> xc =
                new Exchanger<List<Integer>>();
        //CopyOnWriteArrayList允许在列表被遍历时调用remove()方法
        List<Integer>
                producerList = new CopyOnWriteArrayList<Integer>(),
                consumerList = new CopyOnWriteArrayList<Integer>();
        exec.execute(new ExchangerProducer<Integer>(xc,
                new CountingGenerator.Integer(), producerList));
        exec.execute(
                new ExchangerConsumer<Integer>(xc, consumerList));
        TimeUnit.SECONDS.sleep(delay);
        exec.shutdownNow();
    }
}

class ExchangerProducer<T> implements Runnable {
    private Generator<T> generator;
    private Exchanger<List<T>> exchanger;
    private List<T> holder;
    ExchangerProducer(Exchanger<List<T>> exchg,
                      Generator<T> gen, List<T> holder) {
        exchanger = exchg;
        generator = gen;
        this.holder = holder;
    }
    public void run() {
        try {
            while(!Thread.interrupted()) {
                for(int i = 0; i < practice34.size; i++)
                    holder.add(generator.next());
                // 将ExchangerConsumer中的列表替换过来，得到一个空列表，并阻塞
                holder = exchanger.exchange(holder);
            }
        } catch(InterruptedException e) {
            // OK to terminate this way.
        }
    }
}

class ExchangerConsumer<T> implements Runnable {
    private Exchanger<List<T>> exchanger;
    private List<T> holder;
    private volatile T value;
    ExchangerConsumer(Exchanger<List<T>> ex, List<T> holder){
        exchanger = ex;
        this.holder = holder;
    }
    public void run() {
        try {
            while(!Thread.interrupted()) {
                //将ExchangerProducer中的满列表替换过来，并让ExchangerProducer的线程继续运行
                holder = exchanger.exchange(holder);
                for(T x : holder) {
                    value = x; // Fetch out value
                    holder.remove(x); // OK for CopyOnWriteArrayList
                }
            }
        } catch(InterruptedException e) {
            // OK to terminate this way.
        }
        System.out.println("Final value: " + value);
    }
}
